#ifndef __HTTP_PROT_REQUEST_H_
#define __HTTP_PROT_REQUEST_H_

#include <string>
#include <vector>
#include "httpprot_method.h"


namespace httpprot
{
	/**
	 * \brief Class representing HTTP request
	 */
	class Request
	{
	public:
		/**
		 * \brief The status of Request after parsing data
		 */
		enum ParseStatus
		{
			/**
			 * \brief Parsing finished successfully
			 */
			PARSE_OK,

			/**
			 * \brief Parsing cannot be finished because the request in not complete
			 */
			PARSE_INCOMPLETE,

			/**
			 * \brief Parsing failed, may be data is not a valid HTTP request
			 */
			PARSE_ERROR
		};

	public:
		/**
		 * \brief Default constructor, GetParseStatus( ) == PARSE_ERROR
		 */
		Request( ) :
			m_parseStatus( PARSE_ERROR ),
			m_requestData( 0 ),
			m_requestDataLength( 0 ),
			m_requestLength( 0 ),
			m_method( METHOD_GET )
		{
		}

		/**
		 * \brief
		 */
		Request( const char * requestData, unsigned int requestDataLength )
		{
			Parse( requestData, requestDataLength );
		}

		/**
		 * \brief Destructor
		 */
		~Request( )
		{
		}

		/**
		 * \brief
		 */
		ParseStatus Parse( const char * requestData, unsigned int requestDataLength )
		{
			m_parseStatus = PARSE_ERROR;
			m_requestData = requestData;
			m_requestDataLength = requestDataLength;
			m_requestLength = 0;

			parseInternal( );
			return GetParseStatus( );
		}

		/**
		 * \brief
		 */
		ParseStatus GetParseStatus( ) const
		{
			return m_parseStatus;
		}

		unsigned int GetLength( )
		{
			return m_requestLength;
		}

		Method GetMethod( ) const
		{
			return m_method;
		}

		const std::string& GetRequestUri( ) const
		{
			return m_requestUri;
		}

	private:
		std::string readUntilChar( char charToBreak );
		bool testCurChar( char charToTest );
		bool testNextChar( char charToTest );
		bool testIsEndOfData( ) const;
		void skipChars( char charToSkip );
		void skipChar( );
		bool splitHeader( const std::string& s, std::string& keyOut, std::string& valueOut ) const;
		void makeInvalid( ParseStatus parseStatus );
		void parseInternal( );

	private:
		ParseStatus m_parseStatus;
		const char * m_requestData;
		unsigned int m_requestDataLength;
		unsigned int m_requestLength;
		Method m_method;
		std::string m_requestUri;
		std::vector< char > m_message;
	};
};

#endif